//********************************************************************
//	created:	20:5:2013   12:50
//	filename: 	synchelper.h
//	author:		tiamo	
//	purpose:	sync helper
//********************************************************************

#pragma once

namespace utils
{
	//
	// event
	//
	class Event
	{
	public:
		//
		// constructor
		//
		Event()																{mSignalState = false;}

		//
		// destructor
		//
		~Event()															{}

		//
		// signal
		//
		void signal();

		//
		// wait
		//
		bool wait(uint32_t timeout);

	private:
		//
		// mutex
		//
		std::mutex															mMutex;

		//
		// condition variable
		//
		std::condition_variable												mConditionVar;

		//
		// signal state
		//
		volatile bool														mSignalState;
	};

	//
	// thread
	//
	class Thread
	{
	public:
		//
		// constructor
		//
		Thread()															{mThread = nullptr;}

		//
		// destructor
		//
		virtual ~Thread()													{delete mThread;}

		//
		// start
		//
		virtual void start();

		//
		// wait
		//
		void wait();

	private:
		//
		// thread routine
		//
		virtual void run()													{}

	private:
		//
		// thread
		//
		std::thread*														mThread;
	};

	typedef std::recursive_mutex											Mutex;
	
	//
	// Template aliases
	//	[not supported in VS2012]
	//
#if 0
	template<typename T> 
	using Locker = std::lock_guard<T>;
#else
	typedef std::lock_guard<Mutex>											Locker;
#endif

	//
	// resource helper imp
	//
	template<typename Functor>
	class ResourceHelper
	{
	public:
		//
		// constructor
		//
		ResourceHelper(Functor&& functor) : mFunctor(std::forward<Functor>(functor)) {mDismiss = false;}

		//
		// destructor
		//
		~ResourceHelper()													{if(!mDismiss) mFunctor();}

		//
		// move constructor
		//
		ResourceHelper(ResourceHelper<Functor>&& rhs):mFunctor(std::move(rhs.mFunctor)) {mDismiss = rhs.mDismiss; rhs.mDismiss = true;}

		//
		// move assignment
		//
		ResourceHelper<Functor>& operator=(ResourceHelper<Functor>&& rhs)	{if(this != &rhs){mDismiss = rhs.mDismiss; mFunctor = std::move(mFunctor); rhs.mDismiss = true;}return *this;}

		//
		// dismiss
		//
		void dismiss() const												{mDismiss = true;}

	private:
		//
		// disable copy/assignment
		//
		ResourceHelper(ResourceHelper<Functor> const& rhs);
		ResourceHelper<Functor>& operator=(ResourceHelper<Functor>& rhs);

	private:
		//
		// if this is true, the functor should not be called
		//
		mutable bool														mDismiss;

		//
		// functor
		//
		Functor																mFunctor;
	};

	//
	// helper routine
	//
	template<typename Functor>
	ResourceHelper<Functor> makeResourceHelper(Functor&& functor)			{return ResourceHelper<Functor>(std::forward<Functor>(functor));}
}
